package util

import (
	"strconv"
)

func ToPtr[T any, P Ptr[T]](i T) (o P) {
	return &i
}

func ToObj[P Ptr[T], T any](i P) (o T) {
	return *i
}

func ToPtrs[T any, P Ptr[T]](list []T) []P {
	ptrs := make([]P, len(list))
	for i := range list {
		ptrs[i] = &list[i]
	}
	return ptrs
}

func ToObjs[P Ptr[T], T any](list []P) []T {
	ptrs := make([]T, len(list))
	for i := range list {
		ptrs[i] = *list[i]
	}
	return ptrs
}

func reduce[T any, V any](list []T, conv func(V, T) V, io V) V {
	ret := io
	for i := range list {
		ret = conv(ret, list[i])
	}
	return ret
}

func ReduceWith[T any, V any](list []T, conv func(V, T) V, io V) V {
	return reduce(list, conv, io)
}

func Reduce[T any, V any](list []T, conv func(V, T) V) V {
	var io V
	return reduce(list, conv, io)
}

func ToStr[T Stringable](i T) string {
	switch any(i).(type) {
	case bool:
		return strconv.FormatBool(any(i).(bool))
	case float32, float64:
		return strconv.FormatFloat(any(i).(float64), 'f', -1, 64)
	default:
		return strconv.FormatInt(any(i).(int64), 10)
	}
}
